package gamemodel;

import java.awt.*; 
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
 * This shows how to regulary get updates of the game state and send 
 * it to who ever 
 * @author rogannavarathinarasah
 *
 */
public class GameEngine extends JFrame{

	private GameModel gm; 
	
	private static enum State{
		INITIALIZED, PLAYING, PAUSED, GAMEOVER, DESTROYED
	}
	
	private static State state; 
	private static final int UPDATE_RATE = 4; 
	private static final long UPDATE_PERIOD = 1000000000L / UPDATE_RATE ;
	
	private static final int CANVAS_WIDTH = 850; 
	private static final int CANVAS_HEIGHT = 450; 
	private GameCanvas canvas; 
	
	public GameEngine(){
		
		//init game objects
		gameInit(); 
		
		//UI components
		this.canvas = new GameCanvas(); 
		this.canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT)); 
		this.setContentPane(this.canvas); 
		
		this.setDefaultCloseOperation(EXIT_ON_CLOSE); 
		this.pack(); 
		this.setTitle("Test Game"); 
		this.setVisible(true); 
		
		//start the game
		gameStart(); 
	}
	
	public void gameInit(){
		gm = new GameModel(1000, 1);
		gm.addPlayer("rogan", ScoreBoard.TEAM_A);
		gm.addPlayer("vijith", ScoreBoard.TEAM_A);
		gm.addPlayer("ramjith", ScoreBoard.TEAM_A); 
		gm.addPlayer("abc", ScoreBoard.TEAM_A); 
		state = State.INITIALIZED;
	}
	
	// to start and re-start the game 
	public void gameStart(){
		Thread gameThread = new Thread() {
			public void run(){
				gameLoop(); 
			}
		}; 
		
		gameThread.start(); 
	}
	
	public void gameLoop(){
		long beginTime, timeTaken, timeLeft; 
		
		state = State.PLAYING; 
		
		//game loop
		while (true){
			beginTime = System.nanoTime(); 
			
			if (state == State.GAMEOVER) {
				//TODO: ask if user wants to play again
				//if yes - restart
				//if no - remove players from all the list and destroy game gracefully
				break; 
			}
			if (state == State.PLAYING){
				//get incoming message
				
				//update state and detect any collisions
				gameUpdate(); 
			}
			
			this.repaint(); 
			
			//delay timer to meet target delay rate
			timeTaken = System.nanoTime() - beginTime; 
			timeLeft = (UPDATE_PERIOD - timeTaken) / 1000000; //converts to milliseconds
			if (timeLeft < 10) timeLeft = 10; //sets a minimum 
			
			try {
				//yields control to allow other threads to work
				Thread.sleep(timeLeft); 
			} catch (InterruptedException e){
				System.out.println(e); 
			}
		}
	}
	
	public void gameUpdate(){
		gm.tick();
		
		gm.performMove("rogan", 0, 0);
		gm.performMove("vijith", 0, 0);
		gm.performBallMove(); 
		
		if (gm.isGameOver()){
			if (gm.getScoreBoardState() == ScoreBoard.TIME_EXPIRED){
				System.out.println("time expired");
			} else if (gm.getScoreBoardState() == ScoreBoard.TEAM_A_WIN){
				System.out.println("team a wins!");
			} else if (gm.getScoreBoardState() == ScoreBoard.TEAM_B_WIN){
				System.out.println("team b wins!");
			}
			state = State.GAMEOVER; 
		}
	}
	
	private void gameDraw(Graphics g){
		switch (state){
			case INITIALIZED:
			
				//break;
			
			case PLAYING:
				Graphics2D g2d = (Graphics2D)g;
				gm.draw(g2d);
				break;
			case PAUSED:
				System.out.println("paused!");
			break;
			case GAMEOVER:
				System.out.println("gameOver!");
			break;
			
		}
	}
	
	public void gameKeyPressed(int keyCode){
		switch (keyCode){
		case KeyEvent.VK_UP:
			gm.performMove("rogan", 0, -1);
			System.out.println("up");
			break; 
		case KeyEvent.VK_DOWN:
			gm.performMove("rogan", 0, 1);
			System.out.println("down");
			break; 
		case KeyEvent.VK_LEFT:
			gm.performMove("rogan", -1, 0);
			System.out.println("left");
			break; 
		case KeyEvent.VK_RIGHT:
			gm.performMove("rogan", 1, 0);
			System.out.println("right"); 
			break;
		case KeyEvent.VK_SPACE: 
			gm.performKick("rogan"); 
			System.out.println("rogan fired kick!"); 
			break;
		case KeyEvent.VK_SHIFT: 
			gm.performKick("vijith"); 
			System.out.println("vijith fired kick!"); 
			break;
		case KeyEvent.VK_W:
			gm.performMove("vijith", 0, -1);
			break;
		case KeyEvent.VK_S:
			gm.performMove("vijith", 0, 1);
			break;
		case KeyEvent.VK_A:
			gm.performMove("vijith", -1, 0);
			break;
		case KeyEvent.VK_D:
			gm.performMove("vijith", 1, 0);
			break;
		case KeyEvent.VK_R: //resetfield
			gm.resetField();
			break;
		case KeyEvent.VK_T: //change team
			gm.changeTeam("vijith", ScoreBoard.TEAM_SPECTATOR);
			break;
		case KeyEvent.VK_P: //remove player
			gm.removePlayer("vijith");
			break;
		case KeyEvent.VK_C: //change max score
			gm.changeMaxScore(15);
			break;
		case KeyEvent.VK_U: //change time limit
			gm.changeTimeLimit(120); 
			break;
		}
	}
	
	class GameCanvas extends JPanel implements KeyListener {

		public GameCanvas(){
			setFocusable(true); 
			requestFocus(); 
			addKeyListener(this); 
		}
		
		@Override
	    public void paintComponent(Graphics g){
			super.paintComponent(g); 
			Graphics2D g2d = (Graphics2D) g; 
			setBackground(Color.red); 
			
			
			
			gameDraw(g2d); 
		}
		
		@Override
		public void keyPressed(KeyEvent e) {
			gameKeyPressed(e.getKeyCode());
		}

		@Override
		public void keyReleased(KeyEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void keyTyped(KeyEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		
	}
	
	public static void main(String[] args){
		SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run(){
				new GameEngine(); 
			}
		}); 
	}
}
